﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using kk.components.contracts;
using kk.messages.contracts.DataModel;
using LoungeRepo.Core;
using NUnit.Framework;

namespace kk.belegungsadapter.tests
{
    [TestFixture]
    public class testBelegungsAdapter
    {
        [Test]
        public void Erzeuge_Id_für_Vorstellung()
        {
            Assert.AreEqual("20100317-0732@einSaal", BelegungsAdapter.ErzeugeIdFürVorstellung(
                                                     new DateTime(2010, 3, 17, 7, 32, 55), 
                                                     "einSaal"));
        }


        [Test]
        public void Belegungen_einer_Vorstellung_laden()
        {
            DeleteDir("testrepo");
            using (var repo = new LoungeRepository("testrepo"))
            {
                var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('Y', 2), Belegung.Belegungsstati.Reserviert)
                                     };
                repo.Store(belegungen, BelegungsAdapter.ErzeugeIdFürVorstellung(new DateTime(2010, 3, 17, 12, 0, 0), "audimax"));
            }

            using(var repo = new LoungeRepository("testrepo"))
            {
                var sut = new BelegungsAdapter(repo);

                var gefundeneBelegungen = sut.Finde_Belegungen_zu_Vorstellung(new DateTime(2010, 3, 17, 12, 0, 0), "audimax").ToArray();

                Assert.AreEqual(2, gefundeneBelegungen.Length);
                
                Assert.AreEqual(new DateTime(2010, 3, 17, 7, 0, 0), gefundeneBelegungen[0].Vorstellungstermin);
                Assert.AreEqual("1", gefundeneBelegungen[0].Saal);
                Assert.AreEqual('X', gefundeneBelegungen[0].Platz.Reihe);
                Assert.AreEqual(1, gefundeneBelegungen[0].Platz.Platznummer);
                Assert.AreEqual(Belegung.Belegungsstati.Verkauft, gefundeneBelegungen[0].Status);

                Assert.AreEqual(new DateTime(2010, 3, 17, 7, 0, 0), gefundeneBelegungen[1].Vorstellungstermin);
                Assert.AreEqual("1", gefundeneBelegungen[1].Saal);
                Assert.AreEqual('Y', gefundeneBelegungen[1].Platz.Reihe);
                Assert.AreEqual(2, gefundeneBelegungen[1].Platz.Platznummer);
                Assert.AreEqual(Belegung.Belegungsstati.Reserviert, gefundeneBelegungen[1].Status);
            }
        }


        [Test]
        public void Wenn_noch_keine_Belegungen_vorhanden_dann_leere_Liste()
        {
            DeleteDir("testrepo");
            using (var repo = new LoungeRepository("testrepo"))
            {
                var sut = new BelegungsAdapter(repo);

                var gefundeneBelegungen = sut.Finde_Belegungen_zu_Vorstellung(new DateTime(2010, 3, 16, 8, 0, 0), "99").ToArray();

                Assert.AreEqual(0, gefundeneBelegungen.Length);
            }
        }


        [Test]
        public void Belegungen_über_Pin_generieren()
        {
            DeleteDir("testrepo");
            using (var repo = new LoungeRepository("testrepo"))
            {
                var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('Y', 2), Belegung.Belegungsstati.Reserviert),
                                     };
                repo.Store(belegungen, BelegungsAdapter.ErzeugeIdFürVorstellung(new DateTime(2010, 3, 17, 12, 0, 0), "audimax"));

                var sut = new BelegungsAdapter(repo);

                IEnumerable<Platzposition> belegtePlätze=null;
                sut.ProcessBelegungenZuVorstellung(new Request<Vorstellung, IEnumerable<Platzposition>>(new Vorstellung("xyz", new DateTime(2010, 3, 17, 7, 0, 0), "1"), r => belegtePlätze = r));

                Assert.AreEqual(new[] {"X1", "Y2"}, belegtePlätze.Select(p => p.ToString()));
            }
        }


        [Test]
        public void Belegungen_und_Reservierungen_ohne_Konflikte()
        {
            var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "email", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                         new Belegung("0815", "peter", "email", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('Y', 2), Belegung.Belegungsstati.Reserviert),
                                     };

            var anfrage = new Reservierungsanfrage("maria", "email",
                                                   new Vorstellung("t", new DateTime(2010, 3, 17, 7, 0, 0), "1"),
                                                   new[] {new Platzposition('Z', 99)});

            Assert.IsTrue(BelegungsAdapter.Sind_Reservierungswünsche_und_Belegungen_konfliktfrei(belegungen, anfrage));
        }


        [Test]
        public void Belegungen_und_Reservierungen_mit_Konflikten()
        {
            var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "email", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                         new Belegung("0815", "peter", "email", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('Y', 2), Belegung.Belegungsstati.Reserviert),
                                     };

            var anfrage = new Reservierungsanfrage("maria", "email",
                                                   new Vorstellung("t", new DateTime(2010, 3, 17, 7, 0, 0), "1"),
                                                   new[] { new Platzposition('Y', 2) });

            Assert.IsFalse(BelegungsAdapter.Sind_Reservierungswünsche_und_Belegungen_konfliktfrei(belegungen, anfrage));
        }


        [Test]
        public void Aus_Reservierungswünschen_Belegungen_machen()
        {
            var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "email", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                     };

            var anfrage = new Reservierungsanfrage("maria", "marias email",
                                                   new Vorstellung("t", new DateTime(2010, 3, 17, 7, 0, 0), "1"),
                                                   new[] { new Platzposition('Y', 2) });

            BelegungsAdapter.Reservierungswünsche_erfüllen(belegungen, anfrage);

            Assert.AreEqual(2, belegungen.Count);
        }


        [Test]
        public void Reservierungen_vornehmen_und_speichern()
        {
            DeleteDir("testrepo");
            using (var repo = new LoungeRepository("testrepo"))
            {
                var belegungen = new List<Belegung>
                                     {
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('X', 1), Belegung.Belegungsstati.Verkauft),
                                         new Belegung("0815", "peter", "e@", 
                                                      new DateTime(2010, 3, 17, 7, 0, 0), "1", 
                                                      new Platzposition('Y', 2), Belegung.Belegungsstati.Reserviert),
                                     };
                repo.Store(belegungen, BelegungsAdapter.ErzeugeIdFürVorstellung(new DateTime(2010, 3, 17, 12, 0, 0), "audimax"));

                var sut = new BelegungsAdapter(repo);

                var anfrage = new Reservierungsanfrage("maria", "email",
                                                       new Vorstellung("t", new DateTime(2010, 3, 17, 7, 0, 0), "1"),
                                                       new[] { new Platzposition('Z', 99) });

                Reservierungsbestätigung rbest = null;
                sut.ProcessReservierungsanfrage(new Request<Reservierungsanfrage, Reservierungsbestätigung>(anfrage, r => rbest = r));

                Assert.IsTrue(rbest.ReservierungErfolgreich);
            }

            using (var repo = new LoungeRepository("testrepo"))
            {
                var belegungen = repo.Load<IEnumerable<Belegung>>(BelegungsAdapter.ErzeugeIdFürVorstellung(new DateTime(2010, 3, 17, 12, 0, 0), "audimax"));
                Assert.AreEqual(3, belegungen.Count());
                Assert.AreEqual("Z99", belegungen.Last().Platz.ToString());
            }
        }



        private void DeleteDir(string path)
        {
            try
            {
                Directory.Delete(path, true);    
            }
            catch(DirectoryNotFoundException){}
        }
    }
}
